package com.xj.nrpc.consumer.client;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.xj.nrpc.consumer.util.RequestEntity;
import com.xj.nrpc.consumer.util.ResponseEntity;

public class DefaultFuture {

	public final static ConcurrentHashMap<String, DefaultFuture> map = new ConcurrentHashMap<String, DefaultFuture>();

	final Lock lock = new ReentrantLock();
	final Condition condition = lock.newCondition();

	private ResponseEntity resp;
	
	private long timeout = 2*60*1000;
	private long startTime = System.currentTimeMillis();

	public DefaultFuture(RequestEntity req) {
		map.put(req.getId(), this);
	}

	public ResponseEntity get() {
		lock.lock();
		try {
			while (!done()) {
				condition.await();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
		return this.resp;
	}
	
	public ResponseEntity get(long timeout) {
		lock.lock();
		try {
			setTimeout(timeout);
			while (!done()) {
				condition.await(timeout,TimeUnit.MILLISECONDS);
				
				if((System.currentTimeMillis() - startTime) > timeout){
					System.out.println("超时");
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
		return this.resp;
	}

	public static void recive(ResponseEntity resp) {
		DefaultFuture def = map.get(resp.getId());
		if (def != null) {
			Lock lock = def.lock;
			lock.lock();
			try {
				def.setResp(resp);
				def.condition.signal();
				map.remove(resp.getId());
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}

	public ResponseEntity getResp() {
		return resp;
	}

	public void setResp(ResponseEntity resp) {
		this.resp = resp;
	}

	private boolean done() {
		if (this.resp != null) {
			return true;
		}
		return false;
	}

	public long getTimeout() {
		return timeout;
	}

	public void setTimeout(long timeout) {
		this.timeout = timeout;
	}

	public long getStartTime() {
		return startTime;
	}

	static class FutureThread extends Thread {
		@Override
		public void run() {
			Set<String> ids = map.keySet();
			for(String id : ids){
				DefaultFuture df = map.get(id);
				if(df == null){
					map.remove(id);
				}else{
					if(df.getTimeout() < (System.currentTimeMillis() - df.getStartTime())){
						ResponseEntity resp = new ResponseEntity();
						resp.setId(id);
						resp.setMsg("超时");
						recive(resp);
					}
				}
			}
		}
	}
	
	static{
		FutureThread ft = new FutureThread();
		ft.setDaemon(true);
		ft.start();
	}
}
